package model

import "math"

type Triangle struct {
	//三角形编号
	Index  int

	//三个顶点
	Points []*Pos

	//相邻的三个三角形的编号索引
	Link   []int

	//距离相邻三角形的距离
	Dist   []int

	//三条边的中点坐标
	Midpts []*Pos

	//三个顶点中最小x坐标值
	MinX   int

	//三个顶点中最小z坐标值
	MinZ   int

	//三个顶点中最大x坐标值
	MaxX   int

	//三个顶点中最大z坐标值
	MaxZ   int

	//面积
	Area2  int
}

/**
判断点是否在三角形内
 */
func (p *Triangle) IsInside(nX,nZ int) bool {
	if nX < p.MinX || nX > p.MaxX || nZ < p.MinZ || nZ > p.MaxZ {
		return false
	}

	total := CalArea2(p.Points[0].x,p.Points[0].z,p.Points[1].x,p.Points[1].z,nX,nZ)
	if total > p.Area2 {
		return false
	}

	total += CalArea2(nX,nZ,p.Points[1].x,p.Points[1].z,p.Points[2].x,p.Points[2].z)
	if total > p.Area2 {
		return false
	}

	total += CalArea2(p.Points[2].x,p.Points[2].z,nX,nZ,p.Points[0].x,p.Points[0].z)
	if total > p.Area2 {
		return false
	}

	return true
}

/**
实例化一个三角形
 */
func NewTriangle(index int,pA,pB,pC *Pos) *Triangle {
	p := &Triangle{
		Points: make([]*Pos,3),
		Link: make([]int,3),
		Dist: make([]int,3),
		Midpts: make([]*Pos,3),
	}

	p.Points[0] = &Pos{
		x: pA.x,
		y: pA.y,
		z: pA.z,
	}

	p.Points[1] = &Pos{
		x: pB.x,
		y: pB.y,
		z: pB.z,
	}

	p.Points[2] = &Pos{
		x: pC.x,
		y: pC.y,
		z: pC.z,
	}

	//设置三个边中点的坐标
	p.Midpts[0] = &Pos{
		x: (p.Points[0].x + p.Points[1].x)/2,
		y: (p.Points[0].y + p.Points[1].y)/2,
		z: (p.Points[0].z + p.Points[1].z)/2,
	}

	p.Midpts[1] = &Pos{
		x: (p.Points[1].x + p.Points[2].x)/2,
		y: (p.Points[1].y + p.Points[2].y)/2,
		z: (p.Points[1].z + p.Points[2].z)/2,
	}

	p.Midpts[2] = &Pos{
		x: (p.Points[2].x + p.Points[0].x)/2,
		y: (p.Points[2].y + p.Points[0].y)/2,
		z: (p.Points[2].z + p.Points[0].z)/2,
	}

	p.MinX = int(math.Min(math.Min(float64(p.Points[0].x),float64(p.Points[1].x)),float64(p.Points[2].x)))
	p.MinZ = int(math.Min(math.Min(float64(p.Points[0].z),float64(p.Points[1].z)),float64(p.Points[2].z)))

	p.MaxX = int(math.Max(math.Max(float64(p.Points[0].x),float64(p.Points[1].x)),float64(p.Points[2].x)))
	p.MaxZ = int(math.Max(math.Max(float64(p.Points[0].z),float64(p.Points[1].z)),float64(p.Points[2].z)))

	p.Area2 = CalArea2(p.Points[0].x,p.Points[0].z,p.Points[1].x,p.Points[1].z,p.Points[2].x,p.Points[2].z)
	return p
}

/**
计算面积
 */
func CalArea2(x1,z1,x2,z2,x3,z3 int) int {
	return int(math.Abs(float64((x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1))))
}